use crate::utils::TimeDomain;
use dashmap::DashMap;
use sonic_rs::Deserialize;
use std::collections::HashSet;
use std::sync::LazyLock;
use strum::EnumString;
use tokio::fs::OpenOptions;
use tokio::io::AsyncWriteExt;
use tokio::sync::OnceCell;

pub static TICKER: LazyLock<DashMap<String, Ticker>> = LazyLock::new(|| DashMap::new());

pub static BINANCE_RULE: OnceCell<HashSet<String>> = OnceCell::const_new();

pub static CONFIG: LazyLock<Config> = LazyLock::new(|| FileDomain::read());

#[derive(Default)]
pub struct Ticker {
    // (买, 卖)
    pub main: (f64, f64),
    pub main_timestamp: i64,
    pub main_bid_amount: f64,
    pub main_ask_amount: f64,

    // (买, 卖)
    pub coinex: (f64, f64),
    pub coinex_timestamp: i64,
    pub coinex_bid_amount: f64,
    pub coinex_ask_amount: f64,
}

#[derive(EnumString)]
#[strum(serialize_all = "PascalCase")]
pub enum Exchange {
    Bitget,
    Ourbit,
    Lbank,
    Xt,
    Btse,
}

#[derive(Deserialize)]
pub struct Config {
    pub exchange: String,
    pub split: u8,
    pub node: u8,
    pub proxy: String,

    pub write_path: String,
}

struct FileDomain;

impl FileDomain {
    fn read() -> Config {
        let config = std::fs::read_to_string("config.toml").unwrap();
        let config: Config = toml::from_str(&config).unwrap();
        config
    }

    async fn write(content: &str, file_path: &str) {
        let mut file = OpenOptions::new()
            .create(true) // 文件不存在时创建
            .append(true) // 以追加模式打开
            .open(file_path)
            .await
            .unwrap();

        file.write_all(content.as_bytes()).await.unwrap();
        file.flush().await.unwrap(); // 确保数据写入磁盘
    }
}

pub async fn callback(symbol: String) {
    let cache = { TICKER.get(&symbol).unwrap() };

    if cache.main.0 == 0.0 || cache.coinex.0 == 0.0 {
        return;
    }

    let file_name = format!(
        "{}{}/Binance_{}_{}.csv",
        CONFIG.write_path,
        TimeDomain::get_date(),
        CONFIG.exchange,
        symbol
    );

    let content = format!(
        "{},{},{},{},{},{},{},{},{},{}\n",
        cache.main.0,
        cache.main.1,
        cache.main_bid_amount,
        cache.main_ask_amount,
        cache.main_timestamp,
        cache.coinex.0,
        cache.coinex.1,
        cache.coinex_bid_amount,
        cache.coinex_ask_amount,
        cache.coinex_timestamp,
    );

    FileDomain::write(&content, &file_name).await;
}
